package manager

import (
	"fmt"
	"strings"
)

/*
MaxHeight 出于forks 过程安全的考虑，比如代码更新，出现了新的fork，旧的链只要不明确指定 fork的高度，那么默认fork高度为 MaxHeight
也就是新的代码默认不会被启用，知道使用的人明确指定了fork的高度
*/
const MaxHeight = 10000000000000000

var globalForks *Forks

// GetGlobalForks 获取全局分叉配置信息
func GetGlobalForks() *Forks {
	return globalForks
}

//Forks fork分叉结构体
type Forks struct {
	forks map[string]int64
}

func checkKey(key string) {
	if strings.Contains(key, ".") {
		panic("name must not have dot")
	}
}

//SetFork 设置fork信息
func (f *Forks) SetFork(key string, height int64) {
	checkKey(key)
	f.setFork(key, height)
}

//ReplaceFork 替换fork信息
func (f *Forks) ReplaceFork(key string, height int64) {
	checkKey(key)
	f.replaceFork(key, height)
}

//SetDappFork 设置dapp的fork信息
func (f *Forks) SetDappFork(dapp, key string, height int64) {
	checkKey(key)
	f.setFork(dapp+"."+key, height)
}

//ReplaceDappFork 替换dapp的fork信息
func (f *Forks) ReplaceDappFork(dapp, key string, height int64) {
	checkKey(key)
	f.replaceFork(dapp+"."+key, height)
}

func (f *Forks) replaceFork(key string, height int64) {
	if f.forks == nil {
		f.forks = make(map[string]int64)
	}
	if _, ok := f.forks[key]; !ok {
		panic("replace a not exist key " + " " + key)
	}
	f.forks[key] = height
}

func (f *Forks) setFork(key string, height int64) {
	if f.forks == nil {
		f.forks = make(map[string]int64)
	}
	f.forks[key] = height
}

// GetFork 如果不存在，那么fork高度为0
func (f *Forks) GetFork(key string) int64 {
	height, ok := f.forks[key]
	if !ok {
		fmt.Errorf("get fork key not exisit -> " + key)
		return MaxHeight
	}
	return height
}

// HasFork fork信息是否存在
func (f *Forks) HasFork(key string) bool {
	_, ok := f.forks[key]
	return ok
}

// GetDappFork 获取dapp fork信息
func (f *Forks) GetDappFork(app string, key string) int64 {
	return f.GetFork(app + "." + key)
}

// SetAllFork 设置所有fork的高度
func (f *Forks) SetAllFork(height int64) {
	for k := range f.forks {
		f.forks[k] = height
	}
}

// GetAll 获取所有fork信息
func (f *Forks) GetAll() map[string]int64 {
	return f.forks
}

// IsFork 是否fork高度
func (f *Forks) IsFork(height int64, fork string) bool {
	ifork := f.GetFork(fork)
	if height == -1 || height >= ifork {
		return true
	}
	return false
}

// IsDappFork 是否dapp fork高度
func (f *Forks) IsDappFork(height int64, dapp, fork string) bool {
	return f.IsFork(height, dapp+"."+fork)
}

// SetDefaultFork 设置默认fork
func (f *Forks) SetDefaultFork() {
	f.SetFork("ForkConsensusUpdate", 110000)

}

func (f *Forks) setLocalFork() {
	f.SetAllFork(0)
	f.ReplaceFork("ForkBlockHash", 1)
	f.ReplaceFork("ForkRootHash", 1)
}

func (f *Forks) setForkForParaZero() {
	f.SetAllFork(0)
	f.ReplaceFork("ForkBlockHash", 1)
	f.ReplaceFork("ForkRootHash", 1)
}
